another-json-schema
Another JSON Schema, simple & flexible & intuitive.
Install
$ npm i another-json-schema --save
Usage
Simple
const AJS = require('another-json-schema')
const userSchema = AJS('userSchema', {
name: { type: 'string', required: true },
age: { type: 'number', gte: 18 },
gender: { type: 'string', enum: ['male', 'female'], default: 'male' },
email: { type: 'string', isEmail: true }
})
console.log(userSchema.validate({ age: 18 }))
const data = { name: 'nswbmw', age: 18 }
console.log(userSchema.validate(data))
console.log(data)
console.log(userSchema.validate({ name: 'nswbmw', age: 18, gender: 'lalala' }))
console.log(userSchema.validate({ name: 'nswbmw', age: 17 }))
console.log(userSchema.validate({ name: 'nswbmw', email: 'myEmail' }))
Nested
const AJS = require('another-json-schema')
const userSchema = AJS('userSchema', {
_id: { type: 'string', pattern: /^[0-9a-z]{24}$/, required: true },
name: { type: 'string' },
age: { type: 'number', gte: 18 },
gender: { type: 'string', enum: ['male', 'female'] }
})
const commentSchema = AJS('commentSchema', {
_id: { type: 'string', pattern: /^[0-9a-z]{24}$/, required: true },
user: userSchema,
content: { type: 'string' }
})
const postSchema = AJS('postSchema', {
_id: { type: 'string', pattern: /^[0-9a-z]{24}$/, required: true },
author: userSchema,
content: { type: 'string' },
comments: [commentSchema]
})
const post = {
_id: 'post11111111111111111111',
author: {
_id: 'user11111111111111111111',
name: 'nswbmw',
age: 100,
gender: 'male',
pet: 'cat'
},
content: 'lalala',
comments: [{
_id: 'comment11111111111111111',
user: {
_id: 'wrong_id',
name: 'user1',
age: 100,
gender: 'male'
},
content: 'sofa'
}]
}
console.log(postSchema.validate(post))
Custom Error Message
const AJS = require('another-json-schema')
const userSchema = AJS('userSchema', {
name: { type: 'string', required: true },
age: {
type: 'number',
gte: 18,
_customErrorMsg: {
gte: '您未满 18 岁'
}
}
})
console.log(userSchema.validate({
name: 'nswbmw',
age: 17
}))
Register validator
const AJS = require('another-json-schema')
AJS.register('adult', function (actual, expected, key, parent) {
return expected ? (actual > 18) : (actual <= 18)
})
const adultSchema = AJS('adultSchema', { type: 'number', adult: true })
console.log(adultSchema.validate(19))
console.log(adultSchema.validate(17))
Custom type validate function
Custom ObjectId validator, check whether ObjectId then wrap _id
string to ObjectId.
const AJS = require('another-json-schema')
const validator = require('validator')
const toObjectId = require('mongodb').ObjectId
function ObjectId(actual, key, parent) {
if (!actual || !validator.isMongoId(actual.toString())) {
return false
}
parent[key] = toObjectId(actual)
return true
}
const postSchema = AJS('postSchema', {
commentIds: [{ type: ObjectId }]
})
const user = {
commentIds: [
'111111111111111111111111',
'222222222222222222222222'
]
}
console.log(postSchema.validate(user))
console.log(postSchema._children.commentIds.validate('lalala'))
Internal type validator
- 'string'
- 'number'
- 'boolean'
- AJS.Types.ObjectId
- AJS.Types.String
- AJS.Types.Number
- AJS.Types.Date
- AJS.Types.Buffer
- AJS.Types.Boolean
- AJS.Types.Mixed
What's difference between number
and AJS.Types.Number
?
number
only check type, AJS.Types.Number
will try to convert value to a number, if failed then throw error.
const AJS = require('/Users/nswbmw/work/GitHub/Node.js/another-json-schema')
const postSchema = AJS('postSchema', {
commentIds: [{ type: AJS.Types.ObjectId }]
})
const user = {
commentIds: [
'111111111111111111111111',
'222222222222222222222222'
]
}
console.log(postSchema.validate(user))
console.log(postSchema._children.commentIds.validate('lalala'))
Ignore validator
const AJS = require('another-json-schema')
const userSchema = AJS('userSchema', {
_id: { type: 'number', range: [1, 100] }
})
const user = {
_id: 0
}
console.log(userSchema.validate(user))
console.log(userSchema.validate(user, { range: false }))
NB: type
validator cannot ignore by passing false
.
API
AJS([name], schema)
Constructor.
AJS.register(name, fn)
Register a validator. eg:
AJS.register('adult', function (actual, expected, key, parent) {
return expected ? (actual > 18) : (actual <= 18)
})
ajs.compile([name], schema)
Compile a schema. The following two ways are the same:
const userSchema = AJS('userSchema', {
_id: { type: 'string', pattern: /^[0-9a-z]{24}$/ },
name: { type: 'string' },
age: { type: 'number', gte: 18 },
gender: { type: 'string', enum: ['male', 'female'] }
})
const newSchema = new AJS()
const userSchema = newSchema.compile('userSchema', {
_id: { type: 'string', pattern: /^[0-9a-z]{24}$/ },
name: { type: 'string' },
age: { type: 'number', gte: 18 },
gender: { type: 'string', enum: ['male', 'female'] }
})
compiledSchema.validate(data, [opts])
Use the compiled validator to validate an object. it will modify the original object and return it:
- valid: {Boolean} wether a valid object
- error: {Error|null}
- message: error message, eg:
($.comments[].user._id: "wrong_id") ✖ (pattern: /^[0-9a-z]{24}$/)
- validator: validator name, eg:
pattern
, - actual: actual value, eg:
wrong_id
, - expected: expected schema, eg:
{ type: 'string', pattern: /^[0-9a-z]{24}$/ }
, - path: path in object, eg:
$.comments[].user._id
, - schema: schema name, eg:
userSchema
- originError: original error thrown from validator
- result: {Any}
opts:
- additionalProperties: {Boolean} if true, retain the original field. default
false
- ignoreNodeType: {Boolean} if true, ignore check node type, like:
[]
. default: false
- gt, gte, lt, lte ...: {Boolean} if false, will not execute this validator.
Built-in validators
- type
- eq|equal
- gt
- gte
- lt
- lte
- range
- enum
- pattern
- default
- required
- all validator's
isXxx
validators, eg: isEmail. type
validator must be string
or AJS.Types.String
.
More examples
see test.
Test
$ npm test (coverage 100%)
License
MIT